package com.tumblr.logico2012.gestures;

import processing.core.PApplet;
import processing.core.PVector;
import SimpleOpenNI.SimpleOpenNI;

/*           ---
 *  		| F	|
 * 		 ---	 ---
 * 		| L	  o	  R	|
 * 		 ---	 ---
 * 			| B	|
 * 			 --- 
 */
public abstract class IControlPad implements IGesture {
	protected int m_userId;
	protected SimpleOpenNI m_context;
	protected PVector ControlPoint;
	protected boolean m_init;
	protected String m_icon;
	protected int m_framecounter;
	protected PApplet p;
	
	// setup  -  initialized for feet 
	protected int SKEL_PART1 = 20;  // kopf=1  linke hand=9  rechte hand=15  linker fuss=20  rechter fuss=24  
	protected int SKEL_PART2 = 24;
	// controls
	protected int m_direction;
	protected boolean m_active;
	
	public final static float CONTROL_BUTTON_WIDTH = 600;
	public final static float CONTROL_MAX_WIDTH = 2000;
	public final static float TIMEOUT = 0.3f; // seconds
		
	public IControlPad(PApplet processor, int userId, SimpleOpenNI context, String icon) {
		p = processor;
		m_userId = userId;
		m_context = context;
		m_direction = -1;
		m_active = false;
		m_init = false;
		m_icon = icon;
		ControlPoint = new PVector();
	}

	public IControlPad(PApplet processor, int userId, SimpleOpenNI context, String icon, boolean use_hands) {
		p = processor;
		m_userId = userId;
		m_context = context;
		m_direction = -1;
		m_active = false;
		m_icon = icon;
		m_init = false;
		ControlPoint = new PVector();
		if (use_hands == true) this.activateHands(); 
	}
		
	// select part of the body to control with
	public void activateHands() {
		this.SKEL_PART1 = 9; 
		this.SKEL_PART2 = 15;		
	}
	
	public void activateFeet() { 
		this.SKEL_PART1 = 20; 
		this.SKEL_PART2 = 24; 
	}

	@Override
	public boolean showBorderOnSelect() { return false; }
	
	@Override
	public boolean checkForStartEvent(GestureManager manager) {
		if(m_active) return false;
		
		PVector pos1 = new PVector(), pos2 = new PVector();			 
		
		if(m_context.getJointPositionSkeleton(this.m_userId, SKEL_PART1, pos1) < 0.001f)
			return false;
		if(m_context.getJointPositionSkeleton(this.m_userId, SKEL_PART2, pos2) < 0.001f)
			return false;

		// are we too far?
		if ((pos1.z < ControlPoint.z - (CONTROL_MAX_WIDTH/2))||(pos2.z < ControlPoint.z - (CONTROL_MAX_WIDTH/2)) ||
				(pos1.z > ControlPoint.z + (CONTROL_MAX_WIDTH/2))||(pos2.z > ControlPoint.z + (CONTROL_MAX_WIDTH/2)) ||
				(pos1.x < ControlPoint.x - (CONTROL_MAX_WIDTH/2))||(pos2.x < ControlPoint.x - (CONTROL_MAX_WIDTH/2)) ||
				(pos1.x > ControlPoint.x + (CONTROL_MAX_WIDTH/2))||(pos2.x > ControlPoint.x + (CONTROL_MAX_WIDTH/2))) {
			this.m_init = false;
			return false;
		}

		// left OR right foot
		if ((pos1.z < ControlPoint.z - (CONTROL_BUTTON_WIDTH/2))||(pos2.z < ControlPoint.z - (CONTROL_BUTTON_WIDTH/2))) {
			this.m_active = true;
			m_framecounter = 0;
			m_direction = IGesture.UP;
			return true;
		}
		if ((pos1.z > ControlPoint.z + (CONTROL_BUTTON_WIDTH/2))||(pos2.z > ControlPoint.z + (CONTROL_BUTTON_WIDTH/2))) {
			this.m_active = true;
			m_framecounter = 0;
			m_direction = IGesture.DOWN;
			return true;
		}
		if ((pos1.x < ControlPoint.x - (CONTROL_BUTTON_WIDTH/2))||(pos2.x < ControlPoint.x - (CONTROL_BUTTON_WIDTH/2))) {
			this.m_active = true;
			m_framecounter = 0;
			m_direction = IGesture.LEFT;
			return true;
		}
		if ((pos1.x > ControlPoint.x + (CONTROL_BUTTON_WIDTH/2))||(pos2.x > ControlPoint.x + (CONTROL_BUTTON_WIDTH/2))) {
			this.m_active =true;
			m_framecounter = 0;
			m_direction = IGesture.RIGHT;
			return true;
		}

		return false;
	}

	@Override
	public boolean checkForStopEvent(GestureManager manager) {
		if(!m_active) return false;
		
		m_framecounter ++;
		
		PVector pos1 = new PVector(), pos2 = new PVector();			 
		
		if(m_context.getJointPositionSkeleton(this.m_userId, SKEL_PART1, pos1) < 0.001f)
			return false;
		if(m_context.getJointPositionSkeleton(this.m_userId, SKEL_PART2, pos2) < 0.001f)
			return false;
		
		if(m_framecounter > TIMEOUT * p.frameRate) {
			this.m_active = false;
			return true;
		}
		// left OR right foot
		switch(m_direction) {
		case IGesture.UP:
			if ((pos1.z > ControlPoint.z - (CONTROL_BUTTON_WIDTH/2))&&(pos2.z > ControlPoint.z - (CONTROL_BUTTON_WIDTH/2))) {
				this.m_active = false;
				return true;
			}
			break;
		case IGesture.DOWN:
			if ((pos1.z < ControlPoint.z + (CONTROL_BUTTON_WIDTH/2))&&(pos2.z < ControlPoint.z + (CONTROL_BUTTON_WIDTH/2))) {
				this.m_active = false;
				return true;
			}
			break;
		case IGesture.LEFT:
			if ((pos1.x > ControlPoint.x - (CONTROL_BUTTON_WIDTH/2))&&(pos2.x > ControlPoint.x - (CONTROL_BUTTON_WIDTH/2))) {
				this.m_active = false;
				return true;
			}
			break;
		case IGesture.RIGHT:
			if ((pos1.x < ControlPoint.x + (CONTROL_BUTTON_WIDTH/2))&&(pos2.x < ControlPoint.x + (CONTROL_BUTTON_WIDTH/2))) {
				this.m_active = false;
				return true;
			}
			break;
		}
		return false;
	}

	@Override
	public String getIcon() {
		return m_icon;
	}

	@Override
	public int getUserId() {
		return m_userId;
	}

	@Override
	public void init(GestureManager manager) {
		PVector pos1 = new PVector(), pos2 = new PVector();	
		
		if(m_context.getJointPositionSkeleton(this.m_userId, SimpleOpenNI.SKEL_LEFT_FOOT, pos1) < 0.001f)
			return;
		if(m_context.getJointPositionSkeleton(this.m_userId, SimpleOpenNI.SKEL_RIGHT_FOOT, pos2) < 0.001f)
			return;
		
		// Mittelpunkt aus beiden Füßen
		ControlPoint.x = (float).5*(pos1.x+pos2.x); 
		ControlPoint.y = (float).5*(pos1.y+pos2.y); 
		ControlPoint.z = (float).5*(pos1.z+pos2.z); 

		PApplet.println("Initialisiere Controlpad");	
		PApplet.println("ControlPoint: x=" + ControlPoint.x + ", y=" + ControlPoint.y + ", z=" + ControlPoint.z);
		
		m_init = true;
	}

	@Override
	public boolean isInit() { return m_init; }
	
	@Override
	public boolean isAborted(GestureManager manager) {
		return false;
	}

	@Override
	public boolean isActive() {
		return m_active;
	}

	@Override
	public void setRefractory(GestureManager manager) {
	}	
}
